
`timescale 1ns / 1ps

module alu_top(
	clk,
	i_reg_file_left,
	i_reg_file_right,
	i_q_reg_left,
	i_q_reg_right,
	i_cin,
	i_instr,
	i_a_addr,
	i_b_addr,
	i_data,

	o_cout,
	o_sign,
	o_zero,
	o_ovf,
	o_reg_file_left,
	o_reg_file_right,
	o_q_reg_left,
	o_q_reg_right,
	o_data
	
);

parameter DATA_WIDTH = 32;

input clk;
input	i_reg_file_left;
input i_reg_file_right;
input	i_q_reg_left;
input	i_q_reg_right;
input	i_cin;
input	[8:0] i_instr;
input	[4:0] i_a_addr;
input	[4:0] i_b_addr;
input [DATA_WIDTH-1:0] i_data;

output o_cout;
output o_sign;
output o_zero;
output o_ovf;
output o_reg_file_left;
output o_reg_file_right;
output o_q_reg_left;
output o_q_reg_right;
output [DATA_WIDTH-1:0] o_data;

wire [DATA_WIDTH-1:0] w_from_mux_to_alu_op_a;
wire [DATA_WIDTH-1:0] w_from_mux_to_alu_op_b;

wire [DATA_WIDTH-1:0] w_from_reg_file_op_a;
wire [DATA_WIDTH-1:0] w_from_reg_file_op_b;
wire [DATA_WIDTH-1:0] w_form_q_reg;
wire [DATA_WIDTH-1:0] w_from_alu_rez;

wire [DATA_WIDTH-1:0] w_from_shifter_to_q_reg;
wire [DATA_WIDTH-1:0] w_from_shifter_to_reg_file;

wire [1:0] 	w_sel_alu_op_a;
wire [1:0] 	w_sel_alu_op_b;
wire [1:0] 	w_cmd_shifter_reg_file;
wire 				w_cmd_reg_file_wr_en;
wire [1:0]	w_cmd_shifter_q_reg;
wire 				w_cmd_q_reg_ld_en;
wire 				w_sel_alu_out;

alu_instr_dec alu_instr_dec_inst(
	.i_instr(i_instr),
	
	.o_sel_alu_op_a(w_sel_alu_op_a),
	.o_sel_alu_op_b(w_sel_alu_op_b),
	.o_cmd_shifter_reg_file(w_cmd_shifter_reg_file),
	.o_cmd_reg_file_wr_en(w_cmd_reg_file_wr_en),
	.o_cmd_shifter_q_reg(w_cmd_shifter_q_reg),
	.o_cmd_q_reg_ld_en(w_cmd_q_reg_ld_en),
	.o_sel_alu_out(w_sel_alu_out)
);

alu alu_inst(
	.i_cin(i_cin),
	.i_func(i_instr[5:3]),
	.i_op_a(w_from_mux_to_alu_op_a),
	.i_op_b(w_from_mux_to_alu_op_b),
	.o_cout(o_cout),
	.o_zero(o_zero),
	.o_ovf(o_ovf),
	.o_sign(o_sign),
	.o_rez(w_from_alu_rez)
);

reg_file reg_file_inst(
	.clk(clk),
	.i_wr_en(w_cmd_reg_file_wr_en),
	.i_a_addr(i_a_addr),
	.i_b_addr(i_b_addr),
	.i_b_data(w_from_shifter_to_reg_file),
	.o_a_data(w_from_reg_file_op_a),
	.o_b_data(w_from_reg_file_op_b)
);

q_reg q_reg_inst(
	.clk(clk),
	.i_ld_en(w_cmd_q_reg_ld_en),
	.i_data(w_from_shifter_to_q_reg),
	.o_data(w_form_q_reg)
);

shifter shifter_for_reg_file_inst(
	.i_left(i_reg_file_left),
	.i_right(i_reg_file_right),
	.i_data(w_from_alu_rez),
	.i_sel(w_cmd_shifter_reg_file),
	.o_left(o_reg_file_left),
	.o_right(o_reg_file_right),
	.o_data(w_from_shifter_to_reg_file)
);

shifterv2 shifterv2_for_q_reg_inst(
	.i_left(i_q_reg_left),
	.i_right(i_q_reg_right),
	.i_data0(w_form_q_reg),
	.i_data1(w_from_alu_rez),
	.i_sel(w_cmd_shifter_q_reg),
	.o_left(o_q_reg_left),
	.o_right(o_q_reg_right),
	.o_data(w_from_shifter_to_q_reg)
);

mux1x4v2 mux1x4v2_for_alu_op_a_inst(
	.i_sel(w_sel_alu_op_a),
	.i_data0(i_data),
	.i_data1(w_from_reg_file_op_a),
	.i_data2({DATA_WIDTH{1'b0}}),
	.i_data3({DATA_WIDTH{1'b0}}),
	.o_data(w_from_mux_to_alu_op_a)
);

mux1x4v2 mux1x4v2_for_alu_op_b_inst(
	.i_sel(w_sel_alu_op_b),
	.i_data0(w_from_reg_file_op_a),
	.i_data1(w_from_reg_file_op_b),
	.i_data2(w_form_q_reg),
	.i_data3({DATA_WIDTH{1'b0}}),
	.o_data(w_from_mux_to_alu_op_b)
);

mux1x2 mux1x2_for_alu_out_inst(
	.i_sel(w_sel_alu_out),
	.i_data0(w_from_reg_file_op_a),
	.i_data1(w_from_alu_rez),
	.o_data(o_data)
);

endmodule
